local app = require "app"
local game = app.game.running
local consts = game.util.consts

local GameObjectExtension = CS.Blaze.GameObjectExtension
local Vector3 = CS.UnityEngine.Vector3

local M = game.ui.element()

M.store_watchers = {
    gameplay = {
        ["玩家下注"] = function(self, store, state, args, initialize)
            if initialize then
                self:clear_chip()
                return
            end

            local no = args.no
            local area_id = args.area_id
            local amount = args.amount
            self:bet(no, area_id, amount)
        end,

        ["阶段变更"] = function(self, store, state, args, initialize)
            if state.phase_id == consts.PHASE_SETTLE then
                for _, obj in pairs(self.on_table_chip) do
                    local index = math.random(#self.roots)
                    local end_pos = self.roots[index].localPosition
                    local x = end_pos.x + math.random(12)
                    local y = end_pos.y + math.random(12)
                    local z = end_pos.z
                    obj.transform:DOLocalMove(Vector3(x, y , z), 0.3)
                end

                game.audio.post("roulette:chip_hula")
            end

            if state.phase_id == consts.PHASE_PAYOUT then
                local count = #self.on_table_chip
                if count == 0 then
                    return
                end

                local times = 10
                local count_per_times = count/times
                count_per_times = math.ceil(count_per_times)

                if self.co then
                    game.coroutine.stop(self.co)
                end

                self.co = game.coroutine.start(function()
                    for index, obj in pairs(self.on_table_chip) do
                        local end_pos = self.others.transform.position
                        obj.transform:DOMove(end_pos, 0.3)
                        :OnComplete(function()
                            count = count - 1
                            if count == 0 then
                                self:clear_chip()
                                game.audio.post("roulette:flytoplayer")
                                self.co = nil
                            end
                        end)

                        if index % count_per_times == 0 then
                            game.coroutine.step(2)
                        end
                    end
                end)
            end
        end
    }
}

function M:ctor(bet_area, seats, others)
    self.res = "club.threecard.roulette/ui/ingame.b:bet_chip"
    self.bet_area = bet_area
    self.seats = seats
    self.others = others
    self.on_table_chip = {}
    self.area_count = {}
    self.roots = {}
end

function M:on_injected()
    table.insert(self.roots, self.root_1)
    table.insert(self.roots, self.root_2)
    table.insert(self.roots, self.root_3)
    table.insert(self.roots, self.root_4)
end

function M:clear_chip()
    for _, obj in pairs(self.on_table_chip) do
        GameObjectExtension.ReturnToPool(obj)
    end

    self.area_count = {}
    self.on_table_chip = {}
end

local function get_bet_indexes(amount)
    local config = game.store.bet_amounts.state.config
    local left_amount = amount

    local k_v = {}
    for i = #config, 1 do
        if i == 1 then
            k_v[i] = math.ceil(left_amount/config[i])
        else
            k_v[i] = math.floor(left_amount/config[i])
            left_amount = left_amount-k_v[i] * config[i]
        end
    end

    local ret = {}
    for k, v in pairs(k_v) do
        for i = 1, v do
            table.insert(ret, k)
        end
    end

    return ret
end

local function get_bet_temp(self, bet_index)
    local temp = nil
    if bet_index == 1 then
        temp = self.chip_1
    elseif bet_index == 2 then
        temp = self.chip_2
    elseif bet_index == 3 then
        temp = self.chip_3
    elseif bet_index == 4 then
        temp = self.chip_4
    else
        temp = self.chip_1
    end

    return temp
end

function M:payout(no, amount, over_handler)
    local indexes = get_bet_indexes(amount)
    local count = #indexes

    if count == 0 then
        if over_handler then
            over_handler()
        end

        return
    end

    local end_pos = self.seats[no].transform.position
    game.coroutine.start(function()
        local left_count = count

        for _, bet_index in ipairs(indexes) do
            local temp = get_bet_temp(bet_index)
            local obj = GameObjectExtension.GetFromPool(temp)
            obj.transform:SetParent(self.on_table_root, false)
            obj.transform.position = self.root_1.position
            obj.transform:DOMove(end_pos, 0.3)
            :OnComplete(function()
                left_count = left_count - 1
                GameObjectExtension.ReturnToPool(obj)
                if left_count == 0 then
                    game.audio.post("roulette:flytoplayer")
                    if over_handler then
                        over_handler()
                    end
                end
            end)

            game.coroutine.step(2)
        end
    end)
end

function M:bet(no, area_id, amount)
    if not self.loaded then
        return
    end

    local bet_index = game.store.bet_amounts.get_bet_index(amount)
    local temp = get_bet_temp(self, bet_index)
    
    local obj = GameObjectExtension.GetFromPool(temp)
    obj.transform:SetParent(self.on_table_root, false)
    table.insert(self.on_table_chip, obj)

    local start_pos = nil
    if no > self.seats.count then   
        start_pos = self.others.transform.position
    else
        start_pos = self.seats[no].transform.position
    end
    local end_pos = self.bet_area.items[area_id]:get_position()
    if not self.area_count[area_id] then
        self.area_count[area_id] = 0
    end
    self.area_count[area_id] = self.area_count[area_id] + 1
    if self.area_count[area_id] > 20 then
        self.area_count[area_id] = 30
    end

    end_pos = Vector3(end_pos.x, end_pos.y + (self.area_count[area_id] - 1) * 0.03, end_pos.z)

    obj.transform.position = start_pos
    obj.transform:DOMove(end_pos, 0.2)
    :OnComplete(function()
        game.audio.post("roulette:bet")
    end)
end

function M:on_release()
    self:super("on_release")

    if self.co then
        game.coroutine.stop(self.co)
        self.co = ni
    end

    self:clear_chip()
end

return M